{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "nB2YsnnkOweh"
      },
      "source": [
        "Copyright 2024 Google. All Rights Reserved.\n",
        "\n",
        "Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "you may not use this file except in compliance with the License.\n",
        "You may obtain a copy of the License at\n",
        "\n",
        "     http://www.apache.org/licenses/LICENSE-2.0\n",
        "\n",
        "Unless required by applicable law or agreed to in writing, software\n",
        "distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "See the License for the specific language governing permissions and\n",
        "limitations under the License."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "oDbJsUhaGBAE"
      },
      "outputs": [],
      "source": [
        "import pandas as pd\n",
        "import jax.numpy as jnp\n",
        "import jax\n",
        "import scipy\n",
        "import numpy as np"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 424
        },
        "executionInfo": {
          "elapsed": 704,
          "status": "ok",
          "timestamp": 1705391056302,
          "user": {
            "displayName": "Martin Bruse",
            "userId": "11653897382912197853"
          },
          "user_tz": -60
        },
        "id": "I1Fqy0vPPKCa",
        "outputId": "57dbef4c-c272-4243-97a4-c5e81b50700c"
      },
      "outputs": [
        {
          "data": {
            "application/vnd.google.colaboratory.intrinsic+json": {
              "summary": "{\n  \"name\": \"data\",\n  \"rows\": 13488,\n  \"fields\": [\n    {\n      \"column\": \"methodA\",\n      \"properties\": {\n        \"dtype\": \"category\",\n        \"samples\": [\n          \"jpegli-q75-yuv420\",\n          \"libjpeg-turbo-q70-yuv420\",\n          \"jpegli-q85-yuv420\"\n        ],\n        \"num_unique_values\": 30,\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"methodB\",\n      \"properties\": {\n        \"dtype\": \"category\",\n        \"samples\": [\n          \"libjpeg-turbo-q65-yuv420\",\n          \"jpegli-q75-yuv444\",\n          \"libjpeg-turbo-q70-yuv420\"\n        ],\n        \"num_unique_values\": 30,\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"originalName\",\n      \"properties\": {\n        \"dtype\": \"category\",\n        \"samples\": [\n          \"164595\",\n          \"225228\",\n          \"5055743\"\n        ],\n        \"num_unique_values\": 49,\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"answerValue\",\n      \"properties\": {\n        \"dtype\": \"category\",\n        \"samples\": [\n          \"A\",\n          \"B\"\n        ],\n        \"num_unique_values\": 2,\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    }\n  ]\n}",
              "type": "dataframe",
              "variable_name": "data"
            },
            "text/html": [
              "\n",
              "  \u003cdiv id=\"df-9bf453a2-e8bd-459f-9f1f-e6e0dd9cfae2\" class=\"colab-df-container\"\u003e\n",
              "    \u003cdiv\u003e\n",
              "\u003cstyle scoped\u003e\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "\u003c/style\u003e\n",
              "\u003ctable border=\"1\" class=\"dataframe\"\u003e\n",
              "  \u003cthead\u003e\n",
              "    \u003ctr style=\"text-align: right;\"\u003e\n",
              "      \u003cth\u003e\u003c/th\u003e\n",
              "      \u003cth\u003emethodA\u003c/th\u003e\n",
              "      \u003cth\u003emethodB\u003c/th\u003e\n",
              "      \u003cth\u003eoriginalName\u003c/th\u003e\n",
              "      \u003cth\u003eanswerValue\u003c/th\u003e\n",
              "    \u003c/tr\u003e\n",
              "  \u003c/thead\u003e\n",
              "  \u003ctbody\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e0\u003c/th\u003e\n",
              "      \u003ctd\u003emozjpeg-q80-yuv422\u003c/td\u003e\n",
              "      \u003ctd\u003ejpegli-q70-yuv444\u003c/td\u003e\n",
              "      \u003ctd\u003e1044329\u003c/td\u003e\n",
              "      \u003ctd\u003eB\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e1\u003c/th\u003e\n",
              "      \u003ctd\u003emozjpeg-q70-yuv420\u003c/td\u003e\n",
              "      \u003ctd\u003elibjpeg-turbo-q75-yuv420\u003c/td\u003e\n",
              "      \u003ctd\u003e792079\u003c/td\u003e\n",
              "      \u003ctd\u003eA\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e2\u003c/th\u003e\n",
              "      \u003ctd\u003emozjpeg-q95-yuv444\u003c/td\u003e\n",
              "      \u003ctd\u003ejpegli-q90-yuv444\u003c/td\u003e\n",
              "      \u003ctd\u003e1420710\u003c/td\u003e\n",
              "      \u003ctd\u003eB\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e3\u003c/th\u003e\n",
              "      \u003ctd\u003emozjpeg-q85-yuv422\u003c/td\u003e\n",
              "      \u003ctd\u003elibjpeg-turbo-q80-yuv422\u003c/td\u003e\n",
              "      \u003ctd\u003epexels-photo-4210863\u003c/td\u003e\n",
              "      \u003ctd\u003eB\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e4\u003c/th\u003e\n",
              "      \u003ctd\u003emozjpeg-q70-yuv420\u003c/td\u003e\n",
              "      \u003ctd\u003ejpegli-q55-yuv444\u003c/td\u003e\n",
              "      \u003ctd\u003e6292444\u003c/td\u003e\n",
              "      \u003ctd\u003eB\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e...\u003c/th\u003e\n",
              "      \u003ctd\u003e...\u003c/td\u003e\n",
              "      \u003ctd\u003e...\u003c/td\u003e\n",
              "      \u003ctd\u003e...\u003c/td\u003e\n",
              "      \u003ctd\u003e...\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e13483\u003c/th\u003e\n",
              "      \u003ctd\u003emozjpeg-q70-yuv420\u003c/td\u003e\n",
              "      \u003ctd\u003ejpegli-q90-yuv444\u003c/td\u003e\n",
              "      \u003ctd\u003e3762075\u003c/td\u003e\n",
              "      \u003ctd\u003eA\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e13484\u003c/th\u003e\n",
              "      \u003ctd\u003elibjpeg-turbo-q80-yuv422\u003c/td\u003e\n",
              "      \u003ctd\u003ejpegli-q85-yuv444\u003c/td\u003e\n",
              "      \u003ctd\u003epexels-photo-2686358\u003c/td\u003e\n",
              "      \u003ctd\u003eA\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e13485\u003c/th\u003e\n",
              "      \u003ctd\u003emozjpeg-q85-yuv422\u003c/td\u003e\n",
              "      \u003ctd\u003ejpegli-q75-yuv444\u003c/td\u003e\n",
              "      \u003ctd\u003e2670327\u003c/td\u003e\n",
              "      \u003ctd\u003eB\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e13486\u003c/th\u003e\n",
              "      \u003ctd\u003ejpegli-q85-yuv444\u003c/td\u003e\n",
              "      \u003ctd\u003ejpegli-q80-yuv444\u003c/td\u003e\n",
              "      \u003ctd\u003eularapi_Semarang_City_Logo\u003c/td\u003e\n",
              "      \u003ctd\u003eB\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e13487\u003c/th\u003e\n",
              "      \u003ctd\u003emozjpeg-q90-yuv444\u003c/td\u003e\n",
              "      \u003ctd\u003ejpegli-q80-yuv444\u003c/td\u003e\n",
              "      \u003ctd\u003epexels-photo-2686358\u003c/td\u003e\n",
              "      \u003ctd\u003eB\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "  \u003c/tbody\u003e\n",
              "\u003c/table\u003e\n",
              "\u003cp\u003e13488 rows × 4 columns\u003c/p\u003e\n",
              "\u003c/div\u003e\n",
              "    \u003cdiv class=\"colab-df-buttons\"\u003e\n",
              "\n",
              "  \u003cdiv class=\"colab-df-container\"\u003e\n",
              "    \u003cbutton class=\"colab-df-convert\" onclick=\"convertToInteractive('df-9bf453a2-e8bd-459f-9f1f-e6e0dd9cfae2')\"\n",
              "            title=\"Convert this dataframe to an interactive table.\"\n",
              "            style=\"display:none;\"\u003e\n",
              "\n",
              "  \u003csvg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\"\u003e\n",
              "    \u003cpath d=\"M120-120v-720h720v720H120Zm60-500h600v-160H180v160Zm220 220h160v-160H400v160Zm0 220h160v-160H400v160ZM180-400h160v-160H180v160Zm440 0h160v-160H620v160ZM180-180h160v-160H180v160Zm440 0h160v-160H620v160Z\"/\u003e\n",
              "  \u003c/svg\u003e\n",
              "    \u003c/button\u003e\n",
              "\n",
              "  \u003cstyle\u003e\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    .colab-df-buttons div {\n",
              "      margin-bottom: 4px;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  \u003c/style\u003e\n",
              "\n",
              "    \u003cscript\u003e\n",
              "      const buttonEl =\n",
              "        document.querySelector('#df-9bf453a2-e8bd-459f-9f1f-e6e0dd9cfae2 button.colab-df-convert');\n",
              "      buttonEl.style.display =\n",
              "        google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "      async function convertToInteractive(key) {\n",
              "        const element = document.querySelector('#df-9bf453a2-e8bd-459f-9f1f-e6e0dd9cfae2');\n",
              "        const dataTable =\n",
              "          await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                    [key], {});\n",
              "        if (!dataTable) return;\n",
              "\n",
              "        const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "          '\u003ca target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb\u003edata table notebook\u003c/a\u003e'\n",
              "          + ' to learn more about interactive tables.';\n",
              "        element.innerHTML = '';\n",
              "        dataTable['output_type'] = 'display_data';\n",
              "        await google.colab.output.renderOutput(dataTable, element);\n",
              "        const docLink = document.createElement('div');\n",
              "        docLink.innerHTML = docLinkHtml;\n",
              "        element.appendChild(docLink);\n",
              "      }\n",
              "    \u003c/script\u003e\n",
              "  \u003c/div\u003e\n",
              "\n",
              "\n",
              "\u003cdiv id=\"df-f69619cd-348a-417b-8c3d-28de9c2430e3\"\u003e\n",
              "  \u003cbutton class=\"colab-df-quickchart\" onclick=\"quickchart('df-f69619cd-348a-417b-8c3d-28de9c2430e3')\"\n",
              "            title=\"Suggest charts\"\n",
              "            style=\"display:none;\"\u003e\n",
              "\n",
              "\u003csvg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "     width=\"24px\"\u003e\n",
              "    \u003cg\u003e\n",
              "        \u003cpath d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/\u003e\n",
              "    \u003c/g\u003e\n",
              "\u003c/svg\u003e\n",
              "  \u003c/button\u003e\n",
              "\n",
              "\u003cstyle\u003e\n",
              "  .colab-df-quickchart {\n",
              "      --bg-color: #E8F0FE;\n",
              "      --fill-color: #1967D2;\n",
              "      --hover-bg-color: #E2EBFA;\n",
              "      --hover-fill-color: #174EA6;\n",
              "      --disabled-fill-color: #AAA;\n",
              "      --disabled-bg-color: #DDD;\n",
              "  }\n",
              "\n",
              "  [theme=dark] .colab-df-quickchart {\n",
              "      --bg-color: #3B4455;\n",
              "      --fill-color: #D2E3FC;\n",
              "      --hover-bg-color: #434B5C;\n",
              "      --hover-fill-color: #FFFFFF;\n",
              "      --disabled-bg-color: #3B4455;\n",
              "      --disabled-fill-color: #666;\n",
              "  }\n",
              "\n",
              "  .colab-df-quickchart {\n",
              "    background-color: var(--bg-color);\n",
              "    border: none;\n",
              "    border-radius: 50%;\n",
              "    cursor: pointer;\n",
              "    display: none;\n",
              "    fill: var(--fill-color);\n",
              "    height: 32px;\n",
              "    padding: 0;\n",
              "    width: 32px;\n",
              "  }\n",
              "\n",
              "  .colab-df-quickchart:hover {\n",
              "    background-color: var(--hover-bg-color);\n",
              "    box-shadow: 0 1px 2px rgba(60, 64, 67, 0.3), 0 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "    fill: var(--button-hover-fill-color);\n",
              "  }\n",
              "\n",
              "  .colab-df-quickchart-complete:disabled,\n",
              "  .colab-df-quickchart-complete:disabled:hover {\n",
              "    background-color: var(--disabled-bg-color);\n",
              "    fill: var(--disabled-fill-color);\n",
              "    box-shadow: none;\n",
              "  }\n",
              "\n",
              "  .colab-df-spinner {\n",
              "    border: 2px solid var(--fill-color);\n",
              "    border-color: transparent;\n",
              "    border-bottom-color: var(--fill-color);\n",
              "    animation:\n",
              "      spin 1s steps(1) infinite;\n",
              "  }\n",
              "\n",
              "  @keyframes spin {\n",
              "    0% {\n",
              "      border-color: transparent;\n",
              "      border-bottom-color: var(--fill-color);\n",
              "      border-left-color: var(--fill-color);\n",
              "    }\n",
              "    20% {\n",
              "      border-color: transparent;\n",
              "      border-left-color: var(--fill-color);\n",
              "      border-top-color: var(--fill-color);\n",
              "    }\n",
              "    30% {\n",
              "      border-color: transparent;\n",
              "      border-left-color: var(--fill-color);\n",
              "      border-top-color: var(--fill-color);\n",
              "      border-right-color: var(--fill-color);\n",
              "    }\n",
              "    40% {\n",
              "      border-color: transparent;\n",
              "      border-right-color: var(--fill-color);\n",
              "      border-top-color: var(--fill-color);\n",
              "    }\n",
              "    60% {\n",
              "      border-color: transparent;\n",
              "      border-right-color: var(--fill-color);\n",
              "    }\n",
              "    80% {\n",
              "      border-color: transparent;\n",
              "      border-right-color: var(--fill-color);\n",
              "      border-bottom-color: var(--fill-color);\n",
              "    }\n",
              "    90% {\n",
              "      border-color: transparent;\n",
              "      border-bottom-color: var(--fill-color);\n",
              "    }\n",
              "  }\n",
              "\u003c/style\u003e\n",
              "\n",
              "  \u003cscript\u003e\n",
              "    async function quickchart(key) {\n",
              "      const quickchartButtonEl =\n",
              "        document.querySelector('#' + key + ' button');\n",
              "      quickchartButtonEl.disabled = true;  // To prevent multiple clicks.\n",
              "      quickchartButtonEl.classList.add('colab-df-spinner');\n",
              "      try {\n",
              "        const charts = await google.colab.kernel.invokeFunction(\n",
              "            'suggestCharts', [key], {});\n",
              "      } catch (error) {\n",
              "        console.error('Error during call to suggestCharts:', error);\n",
              "      }\n",
              "      quickchartButtonEl.classList.remove('colab-df-spinner');\n",
              "      quickchartButtonEl.classList.add('colab-df-quickchart-complete');\n",
              "    }\n",
              "    (() =\u003e {\n",
              "      let quickchartButtonEl =\n",
              "        document.querySelector('#df-f69619cd-348a-417b-8c3d-28de9c2430e3 button');\n",
              "      quickchartButtonEl.style.display =\n",
              "        google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "    })();\n",
              "  \u003c/script\u003e\n",
              "\u003c/div\u003e\n",
              "\n",
              "  \u003cdiv id=\"id_704166d1-522c-47d5-ac12-3c80dad9b1f0\"\u003e\n",
              "    \u003cstyle\u003e\n",
              "      .colab-df-generate {\n",
              "        background-color: #E8F0FE;\n",
              "        border: none;\n",
              "        border-radius: 50%;\n",
              "        cursor: pointer;\n",
              "        display: none;\n",
              "        fill: #1967D2;\n",
              "        height: 32px;\n",
              "        padding: 0 0 0 0;\n",
              "        width: 32px;\n",
              "      }\n",
              "\n",
              "      .colab-df-generate:hover {\n",
              "        background-color: #E2EBFA;\n",
              "        box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "        fill: #174EA6;\n",
              "      }\n",
              "\n",
              "      [theme=dark] .colab-df-generate {\n",
              "        background-color: #3B4455;\n",
              "        fill: #D2E3FC;\n",
              "      }\n",
              "\n",
              "      [theme=dark] .colab-df-generate:hover {\n",
              "        background-color: #434B5C;\n",
              "        box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "        filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "        fill: #FFFFFF;\n",
              "      }\n",
              "    \u003c/style\u003e\n",
              "    \u003cbutton class=\"colab-df-generate\" onclick=\"generateWithVariable('data')\"\n",
              "            title=\"Generate code using this dataframe.\"\n",
              "            style=\"display:none;\"\u003e\n",
              "\n",
              "  \u003csvg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\"\u003e\n",
              "    \u003cpath d=\"M7,19H8.4L18.45,9,17,7.55,7,17.6ZM5,21V16.75L18.45,3.32a2,2,0,0,1,2.83,0l1.4,1.43a1.91,1.91,0,0,1,.58,1.4,1.91,1.91,0,0,1-.58,1.4L9.25,21ZM18.45,9,17,7.55Zm-12,3A5.31,5.31,0,0,0,4.9,8.1,5.31,5.31,0,0,0,1,6.5,5.31,5.31,0,0,0,4.9,4.9,5.31,5.31,0,0,0,6.5,1,5.31,5.31,0,0,0,8.1,4.9,5.31,5.31,0,0,0,12,6.5,5.46,5.46,0,0,0,6.5,12Z\"/\u003e\n",
              "  \u003c/svg\u003e\n",
              "    \u003c/button\u003e\n",
              "    \u003cscript\u003e\n",
              "      (() =\u003e {\n",
              "      const buttonEl =\n",
              "        document.querySelector('#id_704166d1-522c-47d5-ac12-3c80dad9b1f0 button.colab-df-generate');\n",
              "      buttonEl.style.display =\n",
              "        google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "      buttonEl.onclick = () =\u003e {\n",
              "        google.colab.notebook.generateWithVariable('data');\n",
              "      }\n",
              "      })();\n",
              "    \u003c/script\u003e\n",
              "  \u003c/div\u003e\n",
              "\n",
              "    \u003c/div\u003e\n",
              "  \u003c/div\u003e\n"
            ],
            "text/plain": [
              "                        methodA                   methodB  \\\n",
              "0            mozjpeg-q80-yuv422         jpegli-q70-yuv444   \n",
              "1            mozjpeg-q70-yuv420  libjpeg-turbo-q75-yuv420   \n",
              "2            mozjpeg-q95-yuv444         jpegli-q90-yuv444   \n",
              "3            mozjpeg-q85-yuv422  libjpeg-turbo-q80-yuv422   \n",
              "4            mozjpeg-q70-yuv420         jpegli-q55-yuv444   \n",
              "...                         ...                       ...   \n",
              "13483        mozjpeg-q70-yuv420         jpegli-q90-yuv444   \n",
              "13484  libjpeg-turbo-q80-yuv422         jpegli-q85-yuv444   \n",
              "13485        mozjpeg-q85-yuv422         jpegli-q75-yuv444   \n",
              "13486         jpegli-q85-yuv444         jpegli-q80-yuv444   \n",
              "13487        mozjpeg-q90-yuv444         jpegli-q80-yuv444   \n",
              "\n",
              "                     originalName answerValue  \n",
              "0                         1044329           B  \n",
              "1                          792079           A  \n",
              "2                         1420710           B  \n",
              "3            pexels-photo-4210863           B  \n",
              "4                         6292444           B  \n",
              "...                           ...         ...  \n",
              "13483                     3762075           A  \n",
              "13484        pexels-photo-2686358           A  \n",
              "13485                     2670327           B  \n",
              "13486  ularapi_Semarang_City_Logo           B  \n",
              "13487        pexels-photo-2686358           B  \n",
              "\n",
              "[13488 rows x 4 columns]"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "data = pd.read_csv('answers.csv')\n",
        "data"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "executionInfo": {
          "elapsed": 7155,
          "status": "ok",
          "timestamp": 1705391066031,
          "user": {
            "displayName": "Martin Bruse",
            "userId": "11653897382912197853"
          },
          "user_tz": -60
        },
        "id": "Le9uBRlo0U8i",
        "outputId": "e797b9cc-4350-47eb-e245-2f1127741e17"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "result=  message: Desired error not necessarily achieved due to precision loss.\n",
            "  success: False\n",
            "   status: 2\n",
            "      fun: 7355.83447265625\n",
            "        x: [ 1.702e+03  1.747e+03 ...  2.267e+03  2.448e+03]\n",
            "      nit: 37\n",
            "      jac: [ 4.124e-04  1.745e-03 ...  1.090e-03 -4.406e-04]\n",
            " hess_inv: [[ 4.059e+01  3.444e+01 ... -3.696e+01 -3.968e+01]\n",
            "            [ 3.444e+01  3.155e+01 ... -3.387e+01 -3.607e+01]\n",
            "            ...\n",
            "            [-3.696e+01 -3.387e+01 ...  4.109e+01  4.488e+01]\n",
            "            [-3.968e+01 -3.607e+01 ...  4.488e+01  1.075e+02]]\n",
            "     nfev: 97\n",
            "     njev: 86\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "[('libjpeg-turbo-q55-yuv420', 1544.1666960675595),\n",
              " ('libjpeg-turbo-q60-yuv420', 1637.898323179558),\n",
              " ('libjpeg-turbo-q65-yuv420', 1673.7722908631165),\n",
              " ('jpegli-q65-yuv420', 1697.62945079494),\n",
              " ('jpegli-q55-yuv444', 1702.3819453028395),\n",
              " ('mozjpeg-q70-yuv420', 1739.4859576416322),\n",
              " ('jpegli-q60-yuv444', 1746.5323602503968),\n",
              " ('libjpeg-turbo-q70-yuv420', 1764.6265441942764),\n",
              " ('jpegli-q70-yuv420', 1774.358484610835),\n",
              " ('jpegli-q65-yuv444', 1805.7287795052687),\n",
              " ('mozjpeg-q75-yuv420', 1822.4528151830204),\n",
              " ('libjpeg-turbo-q75-yuv420', 1831.2530373401673),\n",
              " ('jpegli-q75-yuv420', 1872.6390413478834),\n",
              " ('jpegli-q70-yuv444', 1898.3800995471095),\n",
              " ('mozjpeg-q80-yuv422', 1963.831148876465),\n",
              " ('jpegli-q80-yuv420', 1988.8932000963903),\n",
              " ('libjpeg-turbo-q80-yuv422', 2000.2437132771747),\n",
              " ('jpegli-q75-yuv444', 2023.39019887469),\n",
              " ('jpegli-q85-yuv420', 2104.1339364762284),\n",
              " ('mozjpeg-q85-yuv422', 2107.951461222033),\n",
              " ('jpegli-q80-yuv444', 2108.894131436216),\n",
              " ('libjpeg-turbo-q85-yuv422', 2114.5248022799215),\n",
              " ('jpegli-q85-yuv444', 2222.368636762056),\n",
              " ('jpegli-q90-yuv420', 2226.033169707306),\n",
              " ('mozjpeg-q90-yuv444', 2267.469649920622),\n",
              " ('libjpeg-turbo-q90-yuv444', 2299.9248934405373),\n",
              " ('jpegli-q90-yuv444', 2333.789854948968),\n",
              " ('jpegli-q95-yuv420', 2357.763196161335),\n",
              " ('mozjpeg-q95-yuv444', 2448.0708192459674),\n",
              " ('libjpeg-turbo-q95-yuv444', 2456.9483632039696),\n",
              " ('jpegli-q95-yuv444', 2464.462707545468)]"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "methods = np.unique(np.concatenate([data['methodA'].unique(), data['methodB'].unique()]))\n",
        "initial_elo = 2000\n",
        "elo_n = 400\n",
        "elos = jnp.ones((len(methods), )) * initial_elo\n",
        "\n",
        "win_count_list = []\n",
        "for method_a in methods:\n",
        "  method_win_list = []\n",
        "  for method_b in methods:\n",
        "    if method_a == method_b:\n",
        "      method_win_list.append(0)\n",
        "    else:\n",
        "      count = data[(data['methodA'] == method_a) \u0026 (data['methodB'] == method_b) \u0026 (data['answerValue'] == 'B')].shape[0]\n",
        "      count += data[(data['methodA'] == method_b) \u0026 (data['methodB'] == method_a) \u0026 (data['answerValue'] == 'A')].shape[0]\n",
        "      method_win_list.append(count)\n",
        "  win_count_list.append(method_win_list)\n",
        "win_count = jnp.asarray(win_count_list)\n",
        "\n",
        "def log_win_prob(elo_a, elo_b):\n",
        "  scaled_elo_a = elo_a * jnp.log(10) / elo_n\n",
        "  scaled_elo_b = elo_b * jnp.log(10) / elo_n\n",
        "  return jax.nn.log_sigmoid(scaled_elo_a - scaled_elo_b)\n",
        "\n",
        "def loss(elos):\n",
        "  shifted_elos = elos - initial_elo\n",
        "  regularizer_factor = 1e-5 / elos.shape[0]\n",
        "  sum_regularizer = 0.9 / elos.shape[0]\n",
        "  accum = -0.5 * regularizer_factor * jnp.square(shifted_elos).sum() - 0.5 * sum_regularizer * jnp.square(shifted_elos.sum())\n",
        "  log_probs = log_win_prob(elos[:, jnp.newaxis], elos[jnp.newaxis, :])\n",
        "  log_probs_scaled = win_count * log_probs\n",
        "  return -(accum + log_probs_scaled.sum())\n",
        "\n",
        "loss_jit = jax.jit(loss)\n",
        "loss_jit_grad = jax.grad(loss_jit)\n",
        "\n",
        "result = scipy.optimize.minimize(loss_jit, elos, jac=loss_jit_grad, method='BFGS')\n",
        "print(f'{result=}')\n",
        "method_scores = list(zip(methods, result.x))\n",
        "method_scores.sort(key=lambda x: x[1])\n",
        "method_scores"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "provenance": [
        {
          "file_id": "17JaGKK8vphUmoyG2XKJ1bINOYTYbsTNA",
          "timestamp": 1705391548677
        },
        {
          "file_id": "1c8_MIWkLF3l5n9nfbxSFhGd7OH9Wkr5x",
          "timestamp": 1701937954626
        },
        {
          "file_id": "1JH9MBIiG4yLv0cakT2D9nFHjFGYF7v6b",
          "timestamp": 1701867820847
        }
      ]
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
